#include "lan8720a_bsp.h"
#include <stdio.h>
#include "FreeRTOS.h"
#include "semphr.h"


ETH_InitTypeDef ETH_InitStructure;

/* 以太网中断配置 */
static void WHT_ETH_NVIC_Config(void)
{
	NVIC_SetPriority(ETH_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY);
	NVIC_EnableIRQ(ETH_IRQn);
}
/* 以太网GPIO初始化 */
static void WHT_ETH_GPIO_Config(void)
{
    /* 使能SYSCFG时钟（用于MII/RMII模式选择） */
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
 
    /* MII/RMII介质接口选择 */
#ifdef MII_MODE
    #ifdef PHY_CLOCK_MCO
        WHT_GPIO_BSP.WHT_Set_Clock(PortA, ENABLE);
        WHT_GPIO_BSP.WHT_Set_Mode(PortA, Pin8, Mode_AF_PP);
        WHT_GPIO_BSP.WHT_Set_AFIO(PortA, Pin8, AFIO_MCO);
        /* Output HSE clock (25MHz) on MCO pin (PA8) to clock the PHY */
        RCC_MCO1Config(RCC_MCO1Source_HSE, RCC_MCO1Div_1);
    #endif /* PHY_CLOCK_MCO */
    SYSCFG_ETH_MediaInterfaceConfig(SYSCFG_ETH_MediaInterface_MII);
#elif defined RMII_MODE
    SYSCFG_ETH_MediaInterfaceConfig(SYSCFG_ETH_MediaInterface_RMII);
#endif

	/* 以太网GPIO时钟 */
    WHT_GPIO_BSP.WHT_Set_Clock(ETH_MDIO_Port, ENABLE);
    WHT_GPIO_BSP.WHT_Set_Clock(ETH_MDC_Port, ENABLE);
    WHT_GPIO_BSP.WHT_Set_Clock(ETH_RMII_REF_CLK_Port, ENABLE);
    WHT_GPIO_BSP.WHT_Set_Clock(ETH_RMII_CRS_DV_Port, ENABLE);
    WHT_GPIO_BSP.WHT_Set_Clock(ETH_RMII_RXD0_Port, ENABLE);
    WHT_GPIO_BSP.WHT_Set_Clock(ETH_RMII_RXD1_Port, ENABLE);
    WHT_GPIO_BSP.WHT_Set_Clock(ETH_RMII_TX_EN_Port, ENABLE);
    WHT_GPIO_BSP.WHT_Set_Clock(ETH_RMII_TXD0_Port, ENABLE);
    WHT_GPIO_BSP.WHT_Set_Clock(ETH_RMII_TXD1_Port, ENABLE);
    WHT_GPIO_BSP.WHT_Set_Clock(ETH_NRST_Port, ENABLE);
 
	/* Configure ETH_NRST */
    WHT_GPIO_BSP.WHT_Set_Pin(ETH_NRST_Port, ETH_NRST_Pin, Low);
    WHT_GPIO_BSP.WHT_Set_Mode(ETH_NRST_Port, ETH_NRST_Pin, Mode_Out_PP);

	/* ETH Reset */
    _eth_delay_(LAN8720A_RESET_DELAY*2);
    WHT_GPIO_BSP.WHT_Set_Pin(ETH_NRST_Port, ETH_NRST_Pin, Hig);
    _eth_delay_(LAN8720A_RESET_DELAY*2);
    
    /* Configure ETH_MDIO */
    WHT_GPIO_BSP.WHT_Set_Mode(ETH_MDIO_Port, ETH_MDIO_Pin, Mode_AF_PP);
    WHT_GPIO_BSP.WHT_Set_AFIO(ETH_MDIO_Port, ETH_MDIO_Pin, AFIO_Ethernet);

    /* Configure ETH_MDC */
    WHT_GPIO_BSP.WHT_Set_Mode(ETH_MDC_Port, ETH_MDC_Pin, Mode_AF_PP);
    WHT_GPIO_BSP.WHT_Set_AFIO(ETH_MDC_Port, ETH_MDC_Pin, AFIO_Ethernet);

    /* Configure ETH_RMII_REF_CLK */
    WHT_GPIO_BSP.WHT_Set_Mode(ETH_RMII_REF_CLK_Port, ETH_RMII_REF_CLK_Pin, Mode_AF_PP);
    WHT_GPIO_BSP.WHT_Set_AFIO(ETH_RMII_REF_CLK_Port, ETH_RMII_REF_CLK_Pin, AFIO_Ethernet);

    /* Configure ETH_RMII_CRS_DV */
    WHT_GPIO_BSP.WHT_Set_Mode(ETH_RMII_CRS_DV_Port, ETH_RMII_CRS_DV_Pin, Mode_AF_PP);
    WHT_GPIO_BSP.WHT_Set_AFIO(ETH_RMII_CRS_DV_Port, ETH_RMII_CRS_DV_Pin, AFIO_Ethernet);

    /* Configure ETH_RMII_RXD0 */
    WHT_GPIO_BSP.WHT_Set_Mode(ETH_RMII_RXD0_Port, ETH_RMII_RXD0_Pin, Mode_AF_PP);
    WHT_GPIO_BSP.WHT_Set_AFIO(ETH_RMII_RXD0_Port, ETH_RMII_RXD0_Pin, AFIO_Ethernet);

    /* Configure ETH_RMII_RXD1 */
    WHT_GPIO_BSP.WHT_Set_Mode(ETH_RMII_RXD1_Port, ETH_RMII_RXD1_Pin, Mode_AF_PP);
    WHT_GPIO_BSP.WHT_Set_AFIO(ETH_RMII_RXD1_Port, ETH_RMII_RXD1_Pin, AFIO_Ethernet);

    /* Configure ETH_RMII_TX_EN */
    WHT_GPIO_BSP.WHT_Set_Mode(ETH_RMII_TX_EN_Port, ETH_RMII_TX_EN_Pin, Mode_AF_PP);
    WHT_GPIO_BSP.WHT_Set_AFIO(ETH_RMII_TX_EN_Port, ETH_RMII_TX_EN_Pin, AFIO_Ethernet);

    /* Configure ETH_RMII_TXD0 */
    WHT_GPIO_BSP.WHT_Set_Mode(ETH_RMII_TXD0_Port, ETH_RMII_TXD0_Pin, Mode_AF_PP);
    WHT_GPIO_BSP.WHT_Set_AFIO(ETH_RMII_TXD0_Port, ETH_RMII_TXD0_Pin, AFIO_Ethernet);

    /* Configure ETH_RMII_TXD1 */
    WHT_GPIO_BSP.WHT_Set_Mode(ETH_RMII_TXD1_Port, ETH_RMII_TXD1_Pin, Mode_AF_PP);
    WHT_GPIO_BSP.WHT_Set_AFIO(ETH_RMII_TXD1_Port, ETH_RMII_TXD1_Pin, AFIO_Ethernet);	
}
/* 以太网MAC配置 */
static void WHT_ETH_MAC_DMA_Config(void)
{
    /* 使能以太网 MAC 和 DMA 时钟 */
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_ETH_MAC, ENABLE);
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_ETH_MAC_Tx, ENABLE);
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_ETH_MAC_Rx, ENABLE);

    /* 复位以太网控制器 */
    ETH_DeInit();
    /* 软件复位 MAC/DMA */
    ETH_SoftwareReset();
    /* 等待软件复位完成 */
    while (ETH_GetSoftwareResetStatus() == SET);
 
    /*------------------------   MAC   -----------------------------------*/
    ETH_StructInit(&ETH_InitStructure);
    ETH_InitStructure.ETH_AutoNegotiation = ETH_AutoNegotiation_Enable;           // 自动协商速率和双工模式
    if (ETH_InitStructure.ETH_AutoNegotiation == ETH_AutoNegotiation_Disable)
    {
        ETH_InitStructure.ETH_Mode             = ETH_Mode_FullDuplex;                // 全双工
	    ETH_InitStructure.ETH_Speed            = ETH_Speed_100M;                     // 速率100M
    }
    ETH_InitStructure.ETH_LoopbackMode         = ETH_LoopbackMode_Disable;           // 禁用回环模式
    ETH_InitStructure.ETH_RetryTransmission    = ETH_RetryTransmission_Disable;      // 禁用重传
    ETH_InitStructure.ETH_AutomaticPadCRCStrip = ETH_AutomaticPadCRCStrip_Disable;   // 禁用自动 CRC 剥离
    ETH_InitStructure.ETH_ReceiveAll           = ETH_ReceiveAll_Disable;             // 不接收所有帧
    ETH_InitStructure.ETH_BroadcastFramesReception = ETH_BroadcastFramesReception_Enable; // 接收广播帧
    ETH_InitStructure.ETH_PromiscuousMode       = ETH_PromiscuousMode_Disable;       // 禁用混杂模式
    ETH_InitStructure.ETH_MulticastFramesFilter = ETH_MulticastFramesFilter_Perfect; // 精确过滤组播帧
    ETH_InitStructure.ETH_UnicastFramesFilter   = ETH_UnicastFramesFilter_Perfect;   // 精确过滤单播帧

#ifdef CHECKSUM_BY_HARDWARE
    ETH_InitStructure.ETH_ChecksumOffload = ETH_ChecksumOffload_Enable;              // 启用硬件校验和
#else
    ETH_InitStructure.ETH_ChecksumOffload = ETH_ChecksumOffload_Disable;             // 禁用硬件校验和
#endif
 
    /*------------------------   DMA   -----------------------------------*/
    /* 错误帧处理 */
    ETH_InitStructure.ETH_DropTCPIPChecksumErrorFrame = ETH_DropTCPIPChecksumErrorFrame_Enable;  // 丢弃校验和错误的帧
	ETH_InitStructure.ETH_ForwardErrorFrames          = ETH_ForwardErrorFrames_Disable;          // 禁止转发错误帧
	ETH_InitStructure.ETH_ForwardUndersizedGoodFrames = ETH_ForwardUndersizedGoodFrames_Disable; // 不转发过小的有效帧
	/* 存储转发模式 */
    ETH_InitStructure.ETH_ReceiveStoreForward  = ETH_ReceiveStoreForward_Enable;  // 接收时完整缓存帧再处理
    ETH_InitStructure.ETH_TransmitStoreForward = ETH_TransmitStoreForward_Enable; // 发送时完整缓存帧再传输
	/* DMA 性能优化 */
    ETH_InitStructure.ETH_AddressAlignedBeats = ETH_AddressAlignedBeats_Enable;         // 地址对齐传输
    ETH_InitStructure.ETH_FixedBurst          = ETH_FixedBurst_Enable;                  // 固定突发长度
    ETH_InitStructure.ETH_RxDMABurstLength    = ETH_RxDMABurstLength_32Beat;            // 32 节拍突发（适合 F4 的 AHB 总线带宽）
    ETH_InitStructure.ETH_TxDMABurstLength    = ETH_TxDMABurstLength_32Beat;            // 32 节拍突发（适合 F4 的 AHB 总线带宽）
    ETH_InitStructure.ETH_DMAArbitration      = ETH_DMAArbitration_RoundRobin_RxTx_2_1; // Rx/Tx 带宽分配 2:1
	/* 多帧处理 */
    ETH_InitStructure.ETH_SecondFrameOperate = ETH_SecondFrameOperate_Enable; // 支持连续处理两帧，提高吞吐率

	// 初始化MAC和DMA
	if (ETH_Init(&ETH_InitStructure, ETHERNET_PHY_ADDRESS) == ETH_SUCCESS)
	{
        /* 使能中断 */
        ETH_DMAITConfig(ETH_DMA_IT_NIS | ETH_DMA_IT_R | ETH_DMA_IT_T, ENABLE);
        PRINT_INFO("ETH Init SUCCESS...\r\n");
	}
	else
	{
		PRINT_ERR("ETH Init Failed...\r\n");
	}
}
 

/* 以太网初始化 */
ErrStatus WHT_ETH_BSP_Init(void)
{
    /* 以太网GPIO配置 */
    WHT_ETH_GPIO_Config();
    /* 以太网中断配置 */
    WHT_ETH_NVIC_Config();
    /* 以太网MAC/DMA配置 */
    WHT_ETH_MAC_DMA_Config();

    uint16_t phy_id1, phy_id2;
    phy_id1 = ETH_ReadPHYRegister(ETHERNET_PHY_ADDRESS, 0x02/*PHY_ID1*/);
    phy_id2 = ETH_ReadPHYRegister(ETHERNET_PHY_ADDRESS, 0x03/*PHY_ID2*/);
    PRINT_INFO("PHY ID: 0x%04X 0x%04X\n", phy_id1, phy_id2);
    PRINT_INFO("PHY State Register = 0x%04x\r\n", ETH_ReadPHYRegister(ETHERNET_PHY_ADDRESS, PHY_BSR));

    if ((ETH_ReadPHYRegister(ETHERNET_PHY_ADDRESS, PHY_BSR) & PHY_Linked_Status) != RESET)
    {
        return SUCCESS;
    }
    else
    {
        return ERROR;
    }
}




extern SemaphoreHandle_t ETH_Rx_xSemaphore;
void ETH_IRQHandler(void)
{
    ETH_DMAClearITPendingBit(ETH_DMA_IT_NIS);

    if (ETH_GetDMAITStatus(ETH_DMA_IT_R) == SET)
    {
        ETH_DMAClearITPendingBit(ETH_DMA_IT_R);

		portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;    
        xSemaphoreGiveFromISR(ETH_Rx_xSemaphore, &xHigherPriorityTaskWoken);
		portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
    }
	else if (ETH_GetDMAITStatus(ETH_DMA_IT_T) == SET)
	{
		ETH_DMAClearITPendingBit(ETH_DMA_IT_T);
		/* 发送完成的中断服务ISR */
        PRINT_INFO("tx test\r\n");
	}
    else if (ETH_GetDMAITStatus(ETH_DMA_IT_AIS) == SET)
    {
        // 处理发送错误
        ETH_DMAClearITPendingBit(ETH_DMA_IT_AIS);
        uint16_t phy_status = ETH_ReadPHYRegister (ETHERNET_PHY_ADDRESS, 0x03); // 读取扩展状态寄存器
        PRINT_ERR("ETH AIS Error! PHY Status: 0x%04X\r\n", phy_status);
    }
}
